# coding: utf-8
from PySide6.QtCore import Property, Qt, Signal
from PySide6.QtGui import QPainter, QPainterPath, QColor, QPen
from PySide6.QtWidgets import QWidget, QAbstractButton, QHBoxLayout, QVBoxLayout, QPushButton, QButtonGroup
from qfluentwidgets import isDarkTheme, themeColor, SingleDirectionScrollArea
from qfluentwidgets.common.animation import BackgroundAnimationWidget


class CardPushButton(BackgroundAnimationWidget, QAbstractButton):
    """ Card Push Button """

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.__userData = {}
        self._isClickEnabled = False
        self._borderRadius = 5
        self.setCheckable(True)
        self.setChecked(False)
        self.setCursor(Qt.CursorShape.PointingHandCursor)

    def _normalBackgroundColor(self):
        return QColor(255, 255, 255, 13 if isDarkTheme() else 170)

    def _hoverBackgroundColor(self):
        return QColor(255, 255, 255, 21 if isDarkTheme() else 64)

    def _pressedBackgroundColor(self):
        return QColor(255, 255, 255, 8 if isDarkTheme() else 64)

    def getBorderRadius(self):
        return self._borderRadius

    def setBorderRadius(self, radius: int):
        self._borderRadius = radius
        self.update()

    def getUserData(self):
        return self.__userData

    def setUserData(self, data: dict):
        self.__userData = data

    def paintEvent(self, e):
        painter = QPainter(self)
        painter.setRenderHints(QPainter.RenderHint.Antialiasing)

        w, h = self.width(), self.height()
        r = self.borderRadius
        d = 2 * r

        isDark = isDarkTheme()
        theme_color = themeColor()

        # draw top border
        path = QPainterPath()
        # path.moveTo(1, h - r)
        path.arcMoveTo(1, h - d - 1, d, d, 240)
        path.arcTo(1, h - d - 1, d, d, 225, -60)
        path.lineTo(1, r)
        path.arcTo(1, 1, d, d, -180, -90)
        path.lineTo(w - r, 1)
        path.arcTo(w - d - 1, 1, d, d, 90, -90)
        path.lineTo(w - 1, h - r)
        path.arcTo(w - d - 1, h - d - 1, d, d, 0, -60)

        topBorderColor = QColor(0, 0, 0, 20)
        if isDark:
            if self.isPressed:
                topBorderColor = QColor(255, 255, 255, 18)
            elif self.isHover:
                topBorderColor = QColor(255, 255, 255, 13)
        else:
            topBorderColor = QColor(0, 0, 0, 15)
        if self.isChecked():
            topBorderColor = theme_color
        painter.strokePath(path, topBorderColor)

        # draw bottom border
        path = QPainterPath()
        path.arcMoveTo(1, h - d - 1, d, d, 240)
        path.arcTo(1, h - d - 1, d, d, 240, 30)
        path.lineTo(w - r - 1, h - 1)
        path.arcTo(w - d - 1, h - d - 1, d, d, 270, 30)

        bottomBorderColor = topBorderColor
        if not isDark and self.isHover and not self.isPressed:
            bottomBorderColor = QColor(0, 0, 0, 27)
        if self.isChecked():
            bottomBorderColor = theme_color
        painter.strokePath(path, bottomBorderColor)

        # draw background
        painter.setPen(Qt.PenStyle.NoPen)
        rect = self.rect().adjusted(1, 1, -1, -1)
        painter.setBrush(self.backgroundColor)
        pen = QPen(bottomBorderColor)
        pen.setWidth(3)
        painter.setPen(pen)
        painter.drawRoundedRect(rect, r, r)

    borderRadius = Property(int, getBorderRadius, setBorderRadius)
    userData = Property(dict, getUserData, setUserData)


class CardListWidget(SingleDirectionScrollArea):
    currentItemChanged = Signal(QAbstractButton)
    itemClicked = Signal(QAbstractButton)

    def __init__(self, parent=None, orient=Qt.Orientation.Vertical):
        super().__init__(parent=parent, orient=orient)
        self.view = QWidget(self)
        if orient == Qt.Orientation.Horizontal:
            self.itemLayout = QHBoxLayout(self.view)
        else:
            self.itemLayout = QVBoxLayout(self.view)
        self.buttonGroup = QButtonGroup(self.view)

        self.buttonGroup.setExclusive(True)
        self.setWidget(self.view)
        self.setWidgetResizable(True)
        self.view.setAutoFillBackground(False)
        self.enableTransparentBackground()

        self.itemLayout.setContentsMargins(0, 0, 11, 0)
        self.itemLayout.setSpacing(10)
        self.itemLayout.setAlignment(Qt.AlignmentFlag.AlignTop)

        self.buttonGroup.buttonClicked.connect(self.itemClicked)
        self.buttonGroup.buttonToggled.connect(self.currentItemChanged)

    def addItem(self, item: CardPushButton):
        """
        向列表中添加一个项目。
        :param item:
        :return:
        """
        item.setAutoExclusive(True)
        self.itemLayout.addWidget(item)
        self.buttonGroup.addButton(item)

    def removeItem(self, item: CardPushButton):
        """
        从列表中删除一个项目。
        :param item: 要删除的项目。
        :return:
        """
        self.itemLayout.removeWidget(item)
        self.buttonGroup.removeButton(item)
        item.deleteLater()

    def removeAllItems(self):
        """
        从列表中删除所有项目。
        :return:
        """
        btn: CardPushButton
        for btn in self.buttonGroup.buttons():
            self.removeItem(btn)

    def currentItem(self) -> CardPushButton:
        """
        获取当前选中的项目。
        :return:
        """
        return self.buttonGroup.checkedButton()

    def setCurrentItem(self, item: CardPushButton):
        """
        设置当前选中的项目。
        :param item:
        :return:
        """
        item.setChecked(True)

    def setCurrentRow(self, ind: int):
        self.buttonGroup.buttons()[ind].setChecked(True)
